const jwtConfig = require('../config/jwt');
const { User } = require('../models');

// 认证中间件
const authenticate = async (request, reply) => {
  try {
    // 从请求头获取令牌
    const authHeader = request.headers.authorization;
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return reply.code(401).send({
        error: 'Unauthorized',
        message: 'Missing or invalid authorization header'
      });
    }
    
    const token = authHeader.substring(7); // 移除 'Bearer ' 前缀
    
    // 验证令牌
    const decoded = jwtConfig.verifyAccessToken(token);
    
    // 查找用户
    const user = await User.findById(decoded.sub);
    if (!user) {
      return reply.code(401).send({
        error: 'Unauthorized',
        message: 'User not found'
      });
    }
    
    // 检查用户状态
    if (user.status !== 'active') {
      return reply.code(401).send({
        error: 'Unauthorized',
        message: 'User account is not active'
      });
    }
    
    // 检查账户是否被锁定
    if (user.isLocked) {
      return reply.code(401).send({
        error: 'Unauthorized',
        message: 'User account is locked'
      });
    }
    
    // 验证租户ID匹配
    if (user.tenantId !== decoded.tenantId) {
      return reply.code(401).send({
        error: 'Unauthorized',
        message: 'Tenant mismatch'
      });
    }
    
    // 将用户信息添加到请求对象
    request.user = {
      id: user._id.toString(),
      tenantId: user.tenantId,
      email: user.email,
      role: user.role,
      fullName: user.fullName,
      permissions: user.permissions
    };
    
  } catch (error) {
    request.log.error('Authentication error:', error);
    return reply.code(401).send({
      error: 'Unauthorized',
      message: 'Invalid token'
    });
  }
};

// 可选认证中间件（不强制要求认证）
const optionalAuthenticate = async (request, reply) => {
  try {
    const authHeader = request.headers.authorization;
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return; // 没有令牌，继续处理
    }
    
    const token = authHeader.substring(7);
    const decoded = jwtConfig.verifyAccessToken(token);
    
    const user = await User.findById(decoded.sub);
    if (user && user.status === 'active' && !user.isLocked && user.tenantId === decoded.tenantId) {
      request.user = {
        id: user._id.toString(),
        tenantId: user.tenantId,
        email: user.email,
        role: user.role,
        fullName: user.fullName,
        permissions: user.permissions
      };
    }
  } catch (error) {
    // 忽略认证错误，继续处理请求
    request.log.warn('Optional authentication failed:', error.message);
  }
};

// 角色检查中间件
const requireRole = (roles) => {
  return async (request, reply) => {
    if (!request.user) {
      return reply.code(401).send({
        error: 'Unauthorized',
        message: 'Authentication required'
      });
    }
    
    const userRoles = Array.isArray(roles) ? roles : [roles];
    
    if (!userRoles.includes(request.user.role)) {
      return reply.code(403).send({
        error: 'Forbidden',
        message: 'Insufficient permissions'
      });
    }
  };
};

// 权限检查中间件
const requirePermission = (resource, action) => {
  return async (request, reply) => {
    if (!request.user) {
      return reply.code(401).send({
        error: 'Unauthorized',
        message: 'Authentication required'
      });
    }
    
    // 管理员拥有所有权限
    if (request.user.role === 'admin') {
      return;
    }
    
    // 检查用户权限
    const hasPermission = request.user.permissions.some(permission => {
      return permission.resource === resource && 
             (permission.actions.includes(action) || permission.actions.includes('manage'));
    });
    
    if (!hasPermission) {
      return reply.code(403).send({
        error: 'Forbidden',
        message: `Permission denied for ${action} on ${resource}`
      });
    }
  };
};

// 租户所有者检查中间件
const requireTenantOwner = async (request, reply) => {
  if (!request.user) {
    return reply.code(401).send({
      error: 'Unauthorized',
      message: 'Authentication required'
    });
  }
  
  if (request.user.role !== 'admin') {
    return reply.code(403).send({
      error: 'Forbidden',
      message: 'Tenant admin access required'
    });
  }
};

// 自己或管理员检查中间件
const requireSelfOrAdmin = (userIdParam = 'id') => {
  return async (request, reply) => {
    if (!request.user) {
      return reply.code(401).send({
        error: 'Unauthorized',
        message: 'Authentication required'
      });
    }
    
    const targetUserId = request.params[userIdParam];
    const isAdmin = request.user.role === 'admin';
    const isSelf = request.user.id === targetUserId;
    
    if (!isAdmin && !isSelf) {
      return reply.code(403).send({
        error: 'Forbidden',
        message: 'Can only access own resources or admin access required'
      });
    }
  };
};

// 租户上下文中间件（确保操作在正确的租户范围内）
const ensureTenantContext = async (request, reply) => {
  if (!request.user) {
    return reply.code(401).send({
      error: 'Unauthorized',
      message: 'Authentication required'
    });
  }
  
  // 将租户ID添加到查询参数中（用于数据过滤）
  request.tenantId = request.user.tenantId;
  
  // 如果请求体中有数据，自动添加租户ID
  if (request.body && typeof request.body === 'object') {
    request.body.tenantId = request.user.tenantId;
  }
};

// API 密钥认证中间件（用于服务间调用）
const authenticateApiKey = async (request, reply) => {
  try {
    const apiKey = request.headers['x-api-key'];
    
    if (!apiKey) {
      return reply.code(401).send({
        error: 'Unauthorized',
        message: 'API key required'
      });
    }
    
    // 这里应该从数据库或配置中验证 API 密钥
    // 暂时使用环境变量中的密钥
    const validApiKey = process.env.API_KEY;
    
    if (apiKey !== validApiKey) {
      return reply.code(401).send({
        error: 'Unauthorized',
        message: 'Invalid API key'
      });
    }
    
    // 标记为 API 请求
    request.isApiRequest = true;
    
  } catch (error) {
    request.log.error('API key authentication error:', error);
    return reply.code(401).send({
      error: 'Unauthorized',
      message: 'API key authentication failed'
    });
  }
};

module.exports = {
  authenticate,
  optionalAuthenticate,
  requireRole,
  requirePermission,
  requireTenantOwner,
  requireSelfOrAdmin,
  ensureTenantContext,
  authenticateApiKey
};